package conn

import (
	"gitee.com/cooge/impush/gutil"
	"gitee.com/cooge/impush/message"
	"gitee.com/cooge/impush/stream"
	"gitee.com/cooge/impush/user"
	"net"
	"time"
)

const (
	DELETE_USER    = -1
	ADD_USER       = 1
	NO_USER        = 0
	DELETE_MACHINE = -2
	ADD_MACHINE    = 2
)

type ClusterHandleFunc func(*ClusterConn, *message.Message, int)

type ClusterConn struct {
	user.UserTCPConn
	clusterHandleFunc ClusterHandleFunc
	ms                *stream.MessageStream
	LiveTime          int
	Close bool
}

var connList = gutil.NewLinkList()

func NewClusterConn(conn *net.TCPConn, clusterHandleFunc ClusterHandleFunc) *ClusterConn {
	return &ClusterConn{UserTCPConn: conn, ms: stream.NewMessageStream(conn), clusterHandleFunc: clusterHandleFunc,LiveTime:30,Close:true}
}

func (cc *ClusterConn) SetReadDeadline() {
	cc.ms.Conn.SetReadDeadline(time.Now().Add(time.Duration(cc.LiveTime) * time.Minute))
}

func (cc *ClusterConn) Start() {
	go cc.start()
}
func (cc *ClusterConn) start() {
	connList.Add(cc)
	cc.Close = false
	for {
		mg, err := cc.ms.ReadMessage()
		if err != nil {
			break
		} else {
			cc.handle(mg)
		}
	}
	cc.Close = true
	connList.Delete(cc)
	go cc.clusterHandleFunc(cc, nil, DELETE_MACHINE)
}
func (cc *ClusterConn) handle(msg *message.Message) {
	ty := msg.Heads.Get(message.TYPE)
	switch ty {
	case message.CLUSTER:
		{
			action := msg.Heads.Get(message.ACTION)
			switch action {
			case message.LIVE:
				{
					cc.clusterHandleFunc(cc, msg, ADD_MACHINE)
					bs := message.ClusterLive()
					cc.ms.Conn.Write(bs)
				}
			case message.SEND_CLUSTER_USER:
				{
					cc.clusterHandleFunc(cc, msg, ADD_USER)
				}
			case message.DELETE_CLUSTER_USER:
				{
					cc.clusterHandleFunc(cc, msg, DELETE_USER)
				}
			case message.NO_USER:
				{
					cc.clusterHandleFunc(cc, msg, NO_USER)
				}

			}
		}
	}
	cc.SetReadDeadline()
}
